The objective of this chapter’s tutorial is to extend your introduction to the Prograph language. The emphasis here is on understanding the form and function of classes and subclasses. You explore the power of class-based inheritance as a mechanism to share attributes and methods for efficient application development. You also see how various forms of overshadowing can be used to override the inheritance mechanism when diversity is desirable.
In chapter 2, “The Grand Tour: Language*396*” you had a brief introduction to the object-oriented feature of Prograph classes. You learned that classes had two main components: attributes and methods, which are their form and function, respectively.
In chapter 3, “The Grand Tour: Application Builder*394*” you used Prograph’s System classes, a powerful collection of interrelated classes and subclasses that simplify the programming of applications with Macintosh interfaces. System classes*1036* are used to initialize and communicate with interface objects implemented by the built-in facilities of the Macintosh operating system and Mac’s hardware-based Toolbox consisting of read-only memory (ROM) chips that contain optimized code and provide the basic behaviors of objects in the Macintosh interface. Instances of System classes are interface objects—window, menu, button, scroll list, and graphic elements, for example.
Prograph provides System classes that define *90*attributes consistent with the Macintosh’s implementation of such interface elements as windows and menus. A Window class item has location and size attributes, for example, so a Get operation can determine where and how large a window is and the window can be moved and resized with a Set operation.
The objects created as instances of the System classes are among the most flashy and visually impressive things you can do with Prograph. But they can also seem complex and distracting—a forest when you want to be studying the trees.
Consequently, this chapter of the tutorials does not use the flashy System classes. This means that examples rely on very basic user-input and output interfaces. Most of what you do in this tutorial uses simple ask, answer, select, show, and display primitives. The “bells and whistles” come later, in the tutorial exploring Prograph’s Application Builder.
t Classes and Instance Attributes
In chapter 5, “The Editor/Interpreter Environment,” you learned about the various data types native to the Prograph environment—boolean, integer, list, macintosh, none, null, real, string, and undefined. Tossing out the three “non-type” types—none, null, and undefined—you are left with what may at first appear to be a paltry variety of data types with which to describe your problem and compute its solution.
This is where classes come into play. The ability to create new classes is Prograph’s mechanism for creating new, more complex data types out of combinations of these basic building blocks. In *902*object-oriented programming, however, you do not talk about new, compound data types—you talk about objects. Objects roll the new data types and the subroutine methods that manipulate those data types into one place: the class.
In chapter 4, “Conceptual Foundations,” you learned about Prograph’s object orientation, which encapsulates attributes and methods within the class definition. Attributes are features of the instances of the class. Methods—roughly analogous to independent program subroutines—are the behaviors known to instances of the class. You are graphically reminded of this encapsulation*319* relationship by Prograph’s class icon. It has an attribute icon embedded on the left and a methods icon on the right. These can be opened to reveal attributes and methods of the class.
 
In non-object-oriented systems, you are often restricted to the range of data types built into the language. Some languages allow you to create new compound data types. In both cases, the structure of data and the code that manipulates it are separated, at least conceptually if not physically.
Prograph, and object-oriented systems in general, bundle the data structure and code intended to manipulate that data structure into the class. An important distinction to understand is that a class is an abstraction, not a thing in itself.
A class is like a cookie cutter. When pressed into rolled-out dough, the cutter determines the shape of the cookie. When an object is created by a Prograph instance generator, the class of the object created determines its attributes. And the methods of the class determine what the object can do (or can have done to it, depending on how you want to look at it).
In this section of the tutorial, you begin to create a*268* discrete-event simulation. Although it is not very complex and not too realistic, it does give you a variety of direct experiences creating Prograph classes and *1022*subclasses as you build an elaborate class system implementing a barnyard and its animal inhabitants.
The design goal of the Barnyard Simulation is simple:
A farmer owns a barnyard that is inhabited by animals. These animals each have a name, an age, and a favorite food. They each know how to move, talk, eat, sleep, and have a birthday.
Four times a year, a barnyard anthropologist takes a “snapshot” of the yard’s activity and transcribes a narrative entry—an event record—in the Yard Study Diary, which hangs on a rope at the gate to the yard. The fourth entry each year records all the animals’ birthdays and their ages, and notes the farmer’s visit to town to buy a new animal.
Your challenge is to bring this simulation scenario to life in Prograph. In doing so, you can gain much experience in creating and manipulating Prograph classes and subclasses.
u Load Prograph and activate the Classes window. Create a new class, Barnyard, and open its Attributes window.
u Create three attributes by Command-clicking three times below the fuzzy gray line in the Barnyard Attributes window. Call the first owner, the second inhabitants, and the third diary. Double-click each attribute icon to open its Value window. Type Farmer Brown in the owner attribute. Set the inhabitants and diary attributes’ default values to list in the scrolling list of data types in their Value windows.
 
So far nothing is new. Barnyard is a class very much like the Person class in the Folks Database you developed in the Grand Tour. The attributes of both the Barnyard and Person classes are instance attributes.
When you create an instance of a particular class, each instance attribute of that object can be set to an independent value. While each instance of a class has the same instance attributes, the value of an attribute can vary from instance to instance. All Cats have the Attribute of weight. But the “Fluffy” instance weighs three pounds and “Felix” weighs fifteen. Similarly, each Barnyard instance has its own diary attribute, metaphorically tied to the post of the gate.
In the Attributes window of a class, instance attributes*499* are triangular icons, always below the horizontal fuzzy gray line in the window. When first created, an Attribute has a NULL value. It can take on any value assigned to it programmatically with a Set Attribute operation, or you can set it to any value directly by opening a Value window.
When you Set an attribute value in the Attributes window of a class, this value becomes the default or starting value of that *91*attribute for each instance*498* of the class created. All Barnyards will initially be owned by Farmer Brown. And the empty lists of the inhabitants and diary attributes will fill with animals and event records, respectively.
t Classes and Class Attributes
*0153*There is another type of attribute associated with classes. A*93* class attribute is “owned” by the class and is known by and accessible by all instances of the class. Class attributes are shared, a kind of OOP Jungian collective memory.
Think back to the Folks Database for a minute. You created a separate object, the persistent People, to store a list of all Person objects created. An equally valid design would have been to create a class attribute, People, in class Person to store the same list.
Objects and their behaviors are a natural way to think about the world. Object-oriented programming provides a natural way to design computer applications that address real-world problems. You think about your application the same way you think about the rest of the world.
In the Folks Database, for example, alternative solutions for the application design can be mapped onto different world views. For example, the persistent-based design suggests there is a large book somewhere with the names of all people in it. Persons objects do not know each other and have to consult the book to find out about each other. On the other hand, the class attribute-based design is a small town model, in which everybody knows everybody else. Each Person instance has access to the class attribute, People, which is a constantly updated list of all Person objects. As soon as a new Person is born, everybody knows about it.
Here is how you create a class attribute.
u Command-click above the gray horizontal line in the Barnyard Attributes*96* window. The class attribute’s icon is hexagonal-shaped to remind you that it is owned by the class and shared by all instances created in that class. Type activeYards to name the class attribute and give it an empty-list default value like the inhabitants and diary instance attributes.
 
The activeYards class attribute is a “holding tank” for any Barnyard instances created. Later, when the simulation gives each animal in a Barnyard a turn to perform some activity, the event processor method will use a Get operation to access the value of the activeYards attribute of the Barnyard class. Since all Barnyard instances have the activeYards attribute, you can obtain the value for activeYards by inputting any Barnyard instance into the Get operation:
 
This is consistent with all the Get attribute operations you have used so far. But there is also a special capability with class attributes that lets you access the class attribute value even if no instance of the class is handy. Instead of inputting an instance to the Get operation, you simply input as a string the name of the class from which you want to get a class attribute.
 
Since you have set the default value of activeYards to a list, you must annotate the terminal of the display primitive with a list input, (…). Test it by accessing a class attribute.
u Create a universal method, inspect yards, and create its first case to look like the method above. If you execute this method now, no Value window is displayed. This indicates that activeYards is empty.
To rectify the situation, begin practicing a routine technique of direct manipulation of classes and instances by way of attributes and Value windows. So far, you have largely created instances and set their attributes programmatically. That is, your methods have included Instance generators,*796**650* Get*391* and Set operations. Application Builder, too, provides a variety of powerful editors that facilitate the creation and changing of System class instances—things like windows, menus, and buttons.
You need to become comfortable, though, with routing around inside Attributes windows and opening Value windows to create and change instances and data values.
u Open the Attributes window of class Barnyard. Double-click to open a Value window on the activeYards class attribute. To test the inspect yards universal method, click between the parentheses of the default empty list in the edit-text pane and type yardA yardB yardC to create a list of strings.
 
u To make it very clear that this list has three elements and that each element is a string, click the*1144* Graphic check box in the Value of Attribute activeYards window. The right-hand Value pane transforms from a text description of the list to a graphic representation of the list, its three elements appearing as attribute icons numbered 1 through 3.
u To confirm that each element is a string, double-click item 3 to open the Value of List Item 3 window.
 
u Close the Value of List Item 3 window. Add a fourth item to the list by Command-clicking between item 1 and 2 in the Value of Attribute activeYards window. The new item appears with a NULL value. The two items below the new item are renumbered as items 3 and 4. Open item 2’s Value window and type yardD, and then close the window. To reorder the list, simply drag item 2 down below item 4 and release the mouse button. The items shift positions, now showing yards A through D. Close the Value window.
u Activate the Universal Methods window and execute inspect yards. One by one you see and then dismiss a Value window for each of the elements in the list of the activeYards class attribute in the Barnyard class.
So accessing a class attribute is not much different from accessing an instance attribute. It should be clear, however, that class attributes are associated with the class and not an instance of the class. Indeed, you have not created a Barnyard instance, but you have set and accessed the activeYards attribute.